home *** CD-ROM | disk | FTP | other *** search
/ The X-Philes (2nd Revision) / The X-Philes Number 1 (1995).iso / xphiles / hp48_1 / browser.tar / browser next >
Text File  |  1990-05-27  |  19KB  |  645 lines

  1. Article 362 of comp.sys.handhelds:
  2. Path: en.ecn.purdue.edu!noose.ecn.purdue.edu!samsung!think!snorkelwacker!tut.cis.ohio-state.edu!uc!norge.unet.umn.edu!fin
  3. From: fin@norge.unet.umn.edu (Craig A. Finseth)
  4. Newsgroups: comp.sys.handhelds
  5. Subject: Browser Routines for the HP-48SX [long message]
  6. Message-ID: <1834@uc.msc.umn.edu>
  7. Date: 24 May 90 20:59:05 GMT
  8. References: <1833@uc.msc.umn.edu>
  9. Sender: news@uc.msc.umn.edu
  10. Organization: Univ Netw Serv, Univ of Minn
  11. Lines: 630
  12.  
  13. >>> This code is for a general-purpose list browser (test routine follows).
  14.  
  15. >>> I will be posting a set of astronomy routines and alamanc in a
  16. week or so.  They use this browser, so if they sound interesting, save
  17. this.
  18.  
  19. Craig A. Finseth            fin@unet.umn.edu [CAF13]
  20. University Networking Services        +1 612 624 3375 desk
  21. University of Minnesota            +1 612 626 1002 FAX
  22. 130 Lind Hall, 207 Church St SE, Minneapolis MN 55455-0134, U.S.A.
  23.  
  24. ------------------------------------------------------------
  25.  
  26. The HP-48SX Browser Instructions and Commented Listing
  27. Version 1.1, 23 May 1990
  28. Copyright (c) 1990 by Jeff Brown, free for personal non-commercial use.
  29. Formatted for monofont (e.g. Courier type for Postscript/Macintosh users)
  30.  
  31. Contents:
  32.  
  33.     Purpose of the Browser
  34.     Parts of the Browser Display
  35.     Browser Keys
  36.     Applications of the Browser
  37.     How to Use the Browser
  38.     Advanced Use of the Browser
  39.     Technical Details of the Browser
  40.     Areas for Improvement
  41.     Browser Commented Listing
  42.     Browser Variables
  43.     Browser Downloadable Listing
  44.  
  45.  
  46. PURPOSE OF THE BROWSER
  47.  
  48. The browser provides a clean, intuitive way for users to browse the
  49. contents of a list and select an item.
  50.  
  51. If you have used the catalog function of the Solver or Plotter, you
  52. have already used a kind of browser.  The browser is not an
  53. application.  It is a user interface tool to be used by your
  54. applications.  At about 1,800 bytes, it is small enough to be used
  55. even in 32K machines.
  56.  
  57. The Browser is a simple to incorporate but powerful programming tool. 
  58. Your users will find it an intuitive and convenient way to choose from
  59. among data items or options.
  60.  
  61. Your program calls the browser with a message and a list on the stack. 
  62. The browser displays your message and list to the user.  It manages
  63. keys and the display, permitting the user to scroll and page through
  64. the list until he finds the appropriate item.  When the user selects
  65. an item, the browser returns its current state, the selected item and
  66. the item's position to the stack.
  67.  
  68. Using the results from a browse, you can change or edit items at the
  69. user's request or choose different execution paths.  Since the browser
  70. returns its state, you can accept the user's choice, take action and
  71. return the user to browsing where he last left off.  This permits some
  72. fairly flashy applications.
  73.  
  74. The browser is very simple to operate but it can be used in so many
  75. ways, it takes a bit of explaining.  If you wish to just give it a
  76. try, skip to the 'How to Use the Browser' section.
  77.  
  78.  
  79. PARTS OF THE BROWSER DISPLAY
  80.  
  81. Description           Example HP-48 display       Display Line Used
  82. -----------------     ----------------------     -----------------
  83. Prompt message ->     Select a company:           Line 1
  84.  
  85.                ->      Apple
  86.               |        Compaq
  87. List pane   --|       >Hewlett-Packard            Lines 2-6
  88.               |        IBM
  89.                ->      Zenith 
  90.  
  91. Scroll bar     ->     <--------####-------->      Line 7
  92.  
  93. The prompt message is your message to the user indicating what is
  94. being browsed and what you expect the user to do.
  95.  
  96. The list pane is a scrolling window onto your list.  There is always a
  97. current item in the window.  This item is displayed with a cursor in
  98. front of it.
  99.  
  100. The scroll bar graphically represents the location of the list pane
  101. within the list. A block of box characters (called a 'thumb')
  102. representing the pane moves along the scroll bar as the user scrolls
  103. through the list. The size of the thumb represents the portion of the
  104. list visible in the pane. The larger the list, the smaller the thumb.
  105.  
  106. Note: the box characters of the thumb are represented here as '#'
  107. since there is no ASCII box character.
  108.  
  109.  
  110. BROWSER KEYS
  111.  
  112. Prefix       Key               Function
  113. -----------  ----------        ---------------------------------------
  114.              Up arrow          scroll up one item
  115. Left-shift   Up arrow          scroll up one page (five items)
  116. Right-shift  Up arrow          go to top of list
  117.              Down arrow        scroll down one item
  118. Left-shift   Down arrow        scroll down one page (five items)
  119. Right-shift  Down arrow        go to bottom of list
  120.              Enter             accept current item
  121.              Backspace         cancel browsing without choosing
  122.  
  123. The left arrow key functions identically to the up arrow and the right
  124. arrow key functions identically to the down arrow.
  125.  
  126.  
  127. APPLICATIONS OF THE BROWSER
  128.  
  129.     - Address or phone number lists
  130.     - Inspectors that let the user delve into the structure of
  131.       objects.
  132.     - Presentation of program options
  133.  
  134. For a good real-live application of the browser, refer to the Almanac program and Astronomy Directory by Craig Finseth and Lauren Nelson.
  135.  
  136.  
  137. HOW TO USE THE BROWSER
  138.  
  139. The browser takes two arguments from the stack.  The simplest way to
  140. call the browser is to put the following arguments on the stack:
  141.  
  142.     Level 2: your message to the user (string)
  143.     Level 1: the list to be browsed (list or name)
  144.  
  145. The browser will take care of the user interaction and return the
  146. following results to the stack:
  147.  
  148.     Level 2: state of the browser (list)
  149.     Level 1: acceptance information (a list) consisting of:
  150.  
  151.         - item selected (type depends on the object),
  152.         - position of the item in the list (real number),
  153.         - 0 if user cancelled or keycode (51.1) if user
  154.           accepted (real number)
  155.  
  156. Example:
  157.  
  158. Peter Palmer, proprietor of Palmer's Polygonal Pies, wishes to record
  159. customer orders using his trusty HP-48SX.  Since pie names are long
  160. and descriptive, it would be best to select the pies from a list.
  161.  
  162. To build a program which takes orders, Peter stores the available
  163. types of pies in a variable:
  164.  
  165.     { "Triangular Treacle" "Raspberry Rhombus" "Pentagonal Plum"
  166.     "Hexagon Hash" "Strawberry Septagon"  "Octagonal Orange Mousse"
  167.     "Nonpareil Nonagon" "Decagonal Delight"} 'pies' STO
  168.  
  169. Next, he writes a little program that takes pie orders.  A fragment
  170. that gets the user's choice of pie looks like this:
  171.  
  172.     "Select a Pie:" pies BROWSE 1 GET 
  173.  
  174. This invokes the browser:
  175.  
  176.     Select a pie:
  177.     >Triangular Treacle
  178.      Raspberry Rhombus
  179.      Pentagonal Praline
  180.      Hexagon Hash
  181.      Strawberry Septagon
  182.     ##############------->
  183.  
  184. After the user chooses a pie, the 1 GET retrieves the description of
  185. the user's chosen pie.  Peter's program could also add the choice to
  186. an order list or use the position of the choice (2 GET) to look up
  187. pricing information from a price list.
  188.  
  189.  
  190. ADVANCED USE OF THE BROWSER
  191.  
  192. If you wish to have the browser start at a particular position in the
  193. list or if you need to specially format your list items for display,
  194. there is an alternate way to call the browser:
  195.  
  196.     Level 2: a list consisting of:
  197.  
  198.         - Your message (string)
  199.         - Current item in list (real number)
  200.         - Lines off-screen above the list pane (real number)
  201.         - Procedure used to format your list items (program)
  202.  
  203.     Level 1: the list to be browsed (list or name)
  204.  
  205. The list in level 2 is the same format as that returned to level 2
  206. when the browser ends.  This is a brief run-down of its parts:
  207.  
  208.     1) Your message to the user
  209.  
  210.     2) The current item (the list position pointed to by the cursor).
  211.  
  212.     3) The lines off-screen tells the browser how far down in the
  213.     list its window should start (if the current item is not visible
  214.     in this area, the list pane will be moved far enough in the
  215.     appropriate direction to include it).
  216.  
  217.     4) The browser will run your program object on each list item
  218.     prior to displaying it.  Your program object should take an item
  219.     (extracted from your list by the browser and placed in level 1)
  220.     and format it for display by the browser.  The browser will call
  221.     this code every time it draws an item in the display so keep it
  222.     fast and simple.
  223.  
  224. This approach is very powerful because you can start the browser in
  225. any position and format its items any way you like.  The list is
  226. returned to you (updated to match the user's actions) when the browser
  227. ends.  This enables you to take the user's response, carry out
  228. appropriate actions and return to browsing the list in the same
  229. position the user left off.  
  230.  
  231. One use of this is to browse hierarchically, that is, browse a list of
  232. lists, returning to the proper place every time the user pops up a
  233. level.  To do this, just keep a list containing your list path and a
  234. matching list containing browser state lists.  When the users pops up
  235. a level, just discard the last item in each list and call the browser
  236. with the new last item.  For example a program for selecting people to
  237. receive mailings might work like this:
  238.  
  239. Select a company:
  240.  Apple
  241.  Compaq
  242. >Hewlett-Packard    User selects company, presses enter
  243.  IBM
  244.  Zenith 
  245. ######################
  246.  
  247.     Select a division:
  248.      Boise
  249.     >Corvallis
  250.      Phoenix        User selects division, presses enter
  251.      Palo Alto
  252.      Santa Clara 
  253.     <-###############---->
  254.  
  255.         Select an Employee:
  256.          Sanders, John
  257.          Terpack, Daniel
  258.          Vogel, Eric        User selects employee (presses enter)
  259.          West, Carmen        (repeat as needed then press backspace)
  260.         >Wickes, William 
  261.         <-------------------#>
  262.  
  263.     Select a division:
  264.      Boise
  265.     >Corvallis
  266.      Phoenix        User is returned to the division browser
  267.      Palo Alto        (with list pane and current item unchanged)
  268.      Santa Clara 
  269.     <-###############---->
  270.  
  271.  
  272. TECHNICAL DETAILS OF THE BROWSER
  273.  
  274. The original version of the browser was a collection of three main
  275. program objects and about two dozen state variables and key handling
  276. objects.  To eliminate the need for a separate browser directory, I
  277. have compressed the whole thing into a single program object (with
  278. considerable loss of readability).
  279.  
  280. The browser has four logical parts:
  281.  
  282.     Browse - sets things up for browsing
  283.  
  284.     MainLoop - waits for key events and hands them off to handlers.
  285.  
  286.     DrawView - draws the browser after key events change it.
  287.  
  288.     Key handlers - interpret the meaning of various keys.
  289.      
  290.  
  291. BROWSE
  292.  
  293. This initialization code is run when the browser is called.  It
  294. extracts the input parameters and puts them in temporary variables. 
  295. It also calculates the size of the thumb.  When Browse finishes setup,
  296. it flows into the main loop.
  297.  
  298. MAINLOOP
  299.  
  300. The main loop is wrapped around the DrawView procedure and the key
  301. handlers.  It loops, drawing the browser and handling keys until the
  302. user accepts an item or aborts the browsing process.
  303.  
  304. DRAWVIEW
  305.  
  306. DrawView checks the current state of the browser and uses one of three
  307. methods to draw the browser's visible parts on the screen.
  308.  
  309. If the list pane is above the current item (the user scrolled down) it
  310. redraws the pane from the bottom up.
  311.  
  312. If the list pane is below the current item (the user scrolled up) it
  313. redraws the pane from the top down.
  314.  
  315. If the current and previous items are both in the pane (the user moved
  316. the cursor within the visible region) only the current and previous
  317. items are redrawn.
  318.  
  319. Originally, I simply drew the lines of the browser from the top down,
  320. every time.  Performance was so slow that when scrolling down, the
  321. display gave the impression that it was scrolling up.  This came about
  322. because the user pressed the down arrow key but saw the top lines of
  323. the display changing first.  To remedy this, I determine which way the
  324. user scrolled and redraw the lines from that direction.  This gives a
  325. satisfying sense of scrolling in the proper direction.
  326.  
  327. To further improve performance, DrawView checks to see if the cursor
  328. has moved out of or into the visible region.  If it has not, only the
  329. previous item and the current item are redrawn.  This cuts drawing
  330. time in half.
  331.  
  332. I decided to implement the scroll bar fairly early in development. 
  333. Browsing a large list can be disorienting. People need to know where
  334. they are in a list and how much progress they are making with each
  335. keystroke. They use the cursor keys differently in large lists than
  336. they do in small lists so constant visual feedback is very valuable.
  337.  
  338.  
  339. AREAS FOR IMPROVEMENT
  340.  
  341. Speed is not as snappy as it ought to be.  Limited redraws take about
  342. 0.8 seconds, full redraws take 1.5 seconds.  The code needs to run
  343. about four times faster.  An assembly language version would improve
  344. this.  Since my Saturn assembly skills are a bit rusty, I will leave
  345. this to others for the time being.
  346.  
  347. I have not tried bit-wise scrolling of the list pane.  It is
  348. conceivable that this might be faster than re-drawing the entire pane
  349. on some occasions.
  350.  
  351. The scroll bar is a bit cheesy in that it is horizontal and the list
  352. is displayed vertically.  This was a practical necessity since there
  353. isn't enough vertical resolution to do it vertically.  Ideally, I
  354. would do a vertical bit-mapped scroll bar.  This would have enough
  355. resolution (48 pixels) for the job.  Again, assembly language might be
  356. the only practical solution.
  357.  
  358. Originally, I planned to take a menu key list and display it so you
  359. could add user-defined features to the browser, but this was torpedoed
  360. by HP's method of handling menus.  There is no supported way to
  361. display a menu and retain program control. A program must halt for the
  362. menu to appear. In short, I can't display your menu and give you back
  363. keycodes when the user presses menu keys. To further exacerbate matters, I can't get rid of the potentially confusing menus already displayed or use the extra line for more items.  Ideas, anyone?
  364.  
  365. I may do some experimentation with binary searches on ordered lists. 
  366. This would permit an 'alpha mode' for the browser so users could press
  367. a letter key and instantly jump to that part of the list.
  368.  
  369. Some applications may want several items from a single browse. Features to permit selection of multiple items (by creating contiguous or non-contiguous selections) before accepting would be useful if user 
  370. interface issues could be resolved. 
  371.  
  372. Features for range selection and Cut/Copy/Paste would be great for
  373. interactive list editing.  This would be a dream for editing programs.
  374.  
  375.  
  376. BROWSER COMMENTED LISTING
  377.  
  378. /* browse  L2: msg | {msg c brOS fmtP} L1: list | name of list */
  379.  
  380. \<<
  381. "by Jeff Brown (612) 646-2478" DROP
  382. "v1.1" DROP
  383. DUP
  384. IF TYPE 6 == THEN        /* if it is a name, get its value */
  385.     EVAL
  386. END
  387. DUP                /* list */
  388. SIZE                /* listL */
  389. DUP 5 MIN            /* brL */
  390. DUP2
  391. 158 CHR                /* loop to build thumb */
  392. \-> l b t
  393. \<<
  394. ""
  395. 1
  396. b l / 22 * 0 RND
  397. FOR i
  398. t +
  399. NEXT
  400. \>>                /* thumb */
  401. "\<---------------------\->"    /* scrB */
  402. 6 ROLL DUP
  403. IF TYPE 5 ==
  404. THEN LIST\-> DROP        /* msg c brOS fmtP */
  405.      ELSE 1 0 \<< \>> {}
  406. END
  407. 3 PICK                /* p */
  408. \<<220 0.125 BEEP\>>        /* eBeep */
  409. 134 CHR                /* cursChr */
  410. 1                /* full */
  411. 1                /* continue */
  412. 1                /* j */
  413. CLLCD
  414. \-> list listL brL thumb scrB msg c brOS fmtP p eBeep cursChr
  415. full continue j
  416.  
  417. \<<
  418. Msg 1 DISP
  419.  
  420. WHILE continue 1 ==
  421. REPEAT
  422.  
  423. /* drawView */
  424.  
  425.      1 DUP 'j' STO brL        /* loop limits */
  426.      CASE
  427.       c brOs s THEN        /* user moved above pane */
  428.            c 1 - 'brOs' STO
  429.            1 'full' STO
  430.       END
  431.       c brOs brL + > THEN    /* user moved below pane */
  432.            DROP2 c brL - 'brOs' STO
  433.            1 'full' STO
  434.            brL 1 -1 'j' STO    /* set new loop limits */
  435.       END
  436.      END
  437.      IF full 1 == THEN        /* full redraw is needed */
  438.       0 'full' STO
  439.       FOR i
  440.            IF i c brOs - = THEN 
  441.             " " list brOs i + GET fmtP EVAL 
  442.             \->STR + i 1 + DISP
  443.            ELSE
  444.             cursChr list brOs i + GET fmtP EVAL 
  445.             \->STR + i 1 + DISP
  446.            END
  447.       J STEP
  448.       c 'p' STO
  449.       scrB brOs listL / 22 * .5 + 0 RND thumb REPL 7 DISP
  450.      ELSE DROP2
  451.       " " list p GET fmtP EVAL \->STR + p brOs - 1 + DISP
  452.       cursChr list c GET fmtP EVAL \->STR + c brOs - 1 + DISP
  453.      END
  454.      3 FREEZE
  455.  
  456. /* mainLoop */
  457.  
  458. 0 WAIT \-> k
  459.      \<<
  460.      IF k FP .3 > THEN k .3 - 'k' STO END
  461.      CASE k IP DUP 35 == SWAP 36 == OR THEN    /* a down key*/
  462.            IF c listL == THEN 
  463.             eBeep EVAL
  464.             ELSE listL            /* bottom of list */
  465.             c DUP DUP 'p' STO
  466.             brL + listL MIN        /* page dn/last item */
  467.             SWAP 1 +            /* item down */
  468.             k FP 10 * ROLL
  469.             'c' STO DROP2        /* choose by keycode */
  470.            END
  471.       END
  472.       k IP DUP 25 == SWAP 34 == OR THEN    /* an up key */
  473.            IF c 1 == THEN
  474.             eBeep EVAL
  475.             ELSE 1            /* top of list */
  476.             c DUP DUP 'p' STO
  477.             brL - 1 MAX            /* page up/1st item */
  478.             SWAP 1 -            /* item up */
  479.             k FP 10 * ROLL        /* choose by keycode */
  480.             'c' STO DROP2
  481.            END
  482.       END
  483.       k 51.1 == THEN            /* enter */
  484.            list c GET c 0 'continue' STO
  485.       END
  486.       k 15.1 == THEN            /* cancel */
  487.            0 DUP 'continue' STO
  488.       END
  489.      END
  490.      \>>
  491. END
  492. {} msg + c + brOS + fmtP +
  493. 3 ROLLD
  494. \>>
  495.  
  496.  
  497. BROWSER VARIABLES
  498.  
  499. continue    boolean        Should waitLoop continue?
  500. full        boolean        Should drawView do entire pane?
  501. cursChr        char        The cursor character
  502. brL        integer        Length (in lines) of list pane
  503. brOs        integer        Items above list pane
  504. c        integer        Position of current item in list
  505. p        integer        Position of previous item in list
  506. msg        string        The prompt message
  507. listL        integer        Number of items in List
  508. list        list        The list being browsed
  509. scrB        sring        22 character image of the scroll bar
  510. thumb        string        The text image for the thumb
  511. j        integer        Loop increment value (-1 or 1)
  512.  
  513.  
  514. BROWSER DOWNLOADABLE LISTING
  515.  
  516. Checksum: #3e2h
  517. Size: 1751
  518. ------------------------------------------------------------
  519. %%HP: T(3)A(D)F(.);
  520. \<< "v1.1" DROP DUP
  521.   IF DTAG TYPE 6 ==
  522.   THEN EVAL
  523.   END DUP SIZE DUP
  524. 5 MIN DUP2 158 CHR
  525. \-> l b t
  526.   \<< "" 1 b l / 22 *
  527. 0 RND
  528.     FOR i t +
  529.     NEXT
  530.   \>>
  531. "\<---------------------\->"
  532. 6 ROLL DUP
  533.   IF DTAG TYPE 5 ==
  534.   THEN LIST\-> DROP
  535.   ELSE 1 0
  536.     \<<
  537.     \>>
  538.   END 3 PICK
  539.   \<< 220 .125 BEEP
  540.   \>> 134 CHR 1 1 1
  541. CLLCD \-> list listL
  542. brL thumb scrB msg
  543. c brOs fmtP p eBeep
  544. cursChr full
  545. continue j
  546.   \<< msg 1 DISP
  547.     WHILE continue
  548. 1 ==
  549.     REPEAT 1 DUP
  550. 'j' STO brL
  551.       CASE c brOs \<=
  552.         THEN c 1 -
  553. 'brOs' STO 1 'full'
  554. STO
  555.         END c brOs
  556. brL + >
  557.         THEN DROP2
  558. c brL - 'brOs' STO
  559. 1 'full' STO brL 1
  560. -1 'j' STO
  561.         END
  562.       END
  563.       IF full 1 ==
  564.       THEN 0 'full'
  565. STO
  566.         FOR i
  567.           IF i c
  568. brOs - \=/
  569.           THEN " "
  570. list brOs i + GET
  571. fmtP EVAL \->STR + i
  572. 1 + DISP
  573.           ELSE
  574. cursChr list brOs i
  575. + GET fmtP EVAL
  576. \->STR + i 1 + DISP
  577.           END j
  578.         STEP c 'p'
  579. STO scrB brOs listL
  580. / 22 * .5 + 0 RND
  581. thumb REPL 7 DISP
  582.       ELSE DROP2
  583. " " list p GET fmtP
  584. EVAL \->STR + p brOs
  585. - 1 + DISP cursChr
  586. list c GET fmtP
  587. EVAL \->STR + c brOs
  588. - 1 + DISP
  589.       END 3 FREEZE
  590. 0 WAIT \-> k
  591.       \<<
  592.         IF k FP .3
  593. >
  594.         THEN k .3 -
  595. 'k' STO
  596.         END
  597.         CASE k IP
  598. DUP 35 == SWAP 36
  599. == OR
  600.           THEN
  601.             IF c
  602. listL ==
  603.             THEN
  604. eBeep EVAL
  605.             ELSE
  606. listL c DUP DUP 'p'
  607. STO brL + listL MIN
  608. SWAP 1 + k FP 10 *
  609. ROLL 'c' STO DROP2
  610.             END
  611.           END k IP
  612. DUP 25 == SWAP 34
  613. == OR
  614.           THEN
  615.             IF c 1
  616. ==
  617.             THEN
  618. eBeep EVAL
  619.             ELSE 1
  620. c DUP DUP 'p' STO
  621. brL - 1 MAX SWAP 1
  622. - k FP 10 * ROLL
  623. 'c' STO DROP2
  624.             END
  625.           END k
  626. 51.1 ==
  627.           THEN list
  628. c GET c k 0
  629. 'continue' STO
  630.           END k
  631. 55.1 ==
  632.           THEN "" 0
  633. DUP DUP 'continue'
  634. STO
  635.           END
  636.         END
  637.       \>>
  638.     END { } msg + c
  639. + brOs + fmtP + 4
  640. ROLLD 3 \->LIST
  641.   \>>
  642. \>>
  643.  
  644.  
  645.